--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/src/backend/self_check.py 9f71f3420c18d5800afb493b723c328d23c7ea12 (9f71f342) Text, 40.08 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Headless / Settings self-check helpers for critical cross-platform diagnostics."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787contextlib
Tff7b72import T7ee787importlib
Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787sys
Tff7b72import T7ee787tempfile
Tff7b72from T7ee787collectionsT7ee787.T7ee787abc Tff7b72import Te6edf3Callable
Tff7b72from T7ee787typing Tff7b72import Te6edf3Any
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3self_check_probe Tff7b72as Te6edf3_self_check_probe T8b949e# noqa: F401
Te6edf3_CRITICAL_IMPORTS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffRNSTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffLXMFTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fflxmfyTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrns_filesyncTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffaiohttpTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbcryptTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffcbor2Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbleakTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebsocketsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpsutilTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3_SELF_CHECK_PROBE_MODULE Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx.src.backend.self_check_probeTa5d6ff"
Te6edf3_MESHCHATX_RUN_MODULE_FLAG Tff7b72= Ta5d6ff"Ta5d6ff--meshchatx-run-moduleTa5d6ff"
Te6edf3SELF_CHECK_LABELS Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffstack_upTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffNetwork Stack Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffconfig_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffConfiguration IntegrityTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdb_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffDatabase Connection Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffread_write_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffStorage Read/Write Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffidentity_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffIdentity Loaded Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffimports_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffCritical Imports Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstorage_lock_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffStorage Lock Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftemp_fs_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffTemp Filesystem Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpublic_assets_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffPublic Assets Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fflxmf_router_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffLXMF Router Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffsubprocess_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffSubprocess Spawn Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrun_module_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffMeshChatX Run-Module Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffsqlite_roundtripTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffSQLite Roundtrip Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffidentity_roundtripTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffIdentity File RoundtripTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffloopback_tcpTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffLoopback TCP Bind Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffunicode_path_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffUnicode Path I/O Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrnode_support_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffRNode Support Module Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbot_launcher_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffBot Launcher Argv Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_status_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP /api/v1/status Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_app_info_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP /api/v1/app/info Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_config_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP /api/v1/config Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_db_health_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Database Health Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Auth CSRF Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_bots_status_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Bots Status Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_security_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Server Security Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_interfaces_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP RNS Interfaces Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_reticulum_instance_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP RNS Instance Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_identities_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Identities Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_favourites_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Favourites Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_telephone_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Telephone Status Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_plugins_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Plugins API Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_plugins_trust_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Plugin Trust List Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_sideband_plugins_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Sideband Plugins Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_sideband_config_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP Sideband Config Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_rrc_hubs_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP RRC Hubs Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_rrc_servers_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffHTTP RRC Servers Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffplugins_runtime_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffPlugin Manager Runtime Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffWebSocket /ws Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebsocket_rns_link_goodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffWebSocket RNS Link API Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffbots_lifecycleTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffBot Create/Start/Stop Ta5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ff_statusTb4b4b4(Te6edf3okTb4b4b4: Tffa657boolTb4b4b4, Te6edf3reasonTb4b4b4: Tffa657str Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffokTa5d6ff" Tff7b72if Te6edf3ok Tff7b72else Ta5d6ff"Ta5d6fffailedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffreasonTa5d6ff"Tb4b4b4: Te6edf3reason Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4}
Tff7b72def Td2a8ffcheck_python_runtimeTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3sysTff7b72.Td2a8ffversion_info Tff7b72< Tb4b4b4(T79c0ff3Tb4b4b4, T79c0ff11Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffPython Tffd700{Te6edf3sysTff7b72.Td2a8ffversion_infoTff7b72.Td2a8ffmajorTffd700}Ta5d6ff.Tffd700{Te6edf3sysTff7b72.Td2a8ffversion_infoTff7b72.Td2a8ffminorTffd700}Ta5d6ff is below 3.11Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sysTff7b72.Td2a8ffexecutable Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffsys.executable is missing: Tffd700{Te6edf3sysTff7b72.Td2a8ffexecutableTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffcheck_critical_importsTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Te6edf3missingTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3errorsTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3name Tff7b72in Te6edf3_CRITICAL_IMPORTSTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3importlibTff7b72.Td2a8ffimport_moduleTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72except Tf85149ModuleNotFoundErrorTb4b4b4:
Te6edf3missingTff7b72.Td2a8ffappendTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3nameTffd700}Ta5d6ff: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3missing Tff7b72or Te6edf3errorsTb4b4b4:
Te6edf3parts Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Te6edf3missingTb4b4b4:
Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ffmissing Ta5d6ff" Tff7b72+ Ta5d6ff"Ta5d6ff, Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3missingTb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3errorsTb4b4b4:
Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6fferrors Ta5d6ff" Tff7b72+ Ta5d6ff"Ta5d6ff | Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3errorsTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ff. Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3partsTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffcheck_identityTb4b4b4(Te6edf3identityTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3identity Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffIdentity is not loadedTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3raw Tff7b72= Tffa657getattrTb4b4b4(Te6edf3identityTb4b4b4, Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3raw Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffIdentity has no hashTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3rawTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4, Tffa657memoryviewTb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3hx Tff7b72= Tffa657bytesTb4b4b4(Te6edf3rawTb4b4b4)Tff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3hx Tff7b72= Tffa657strTb4b4b4(Te6edf3rawTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3hxTb4b4b4) Tff7b72!= T79c0ff32Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffIdentity hash length is Tffd700{Tffa657lenTb4b4b4(Te6edf3hxTb4b4b4)Tffd700}Ta5d6ff, expected 32Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffIdentity check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheck_lxmf_routerTb4b4b4(Te6edf3message_routerTb4b4b4: Te6edf3AnyTb4b4b4, Te6edf3local_destinationTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72if Te6edf3message_router Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffLXMF message router is not initializedTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3local_destination Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffLocal LXMF destination is not availableTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3dest_hash Tff7b72= Tffa657getattrTb4b4b4(Te6edf3local_destinationTb4b4b4, Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3dest_hash Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffLocal LXMF destination has no hashTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffLXMF destination check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffcheck_storage_lockTb4b4b4(Te6edf3base_dirTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Verify StorageLock acquire/contest/release (native flock/msvcrt or soft)."""
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787storage_lock Tff7b72import Te6edf3StorageLockTb4b4b4, Te6edf3StorageLockError
Tff7b72if Tff7b72not Te6edf3base_dir Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3base_dirTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffStorage directory does not existTa5d6ff"Tb4b4b4)
Te6edf3lock_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ff.self_test_storage_lockTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3lock_dirTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3lock_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3lock_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3first Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Te6edf3firstTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Te6edf3mode Tff7b72= Ta5d6ff"Ta5d6ffsoftTa5d6ff" Tff7b72if Tffa657getattrTb4b4b4(Te6edf3firstTb4b4b4, Ta5d6ff"Ta5d6ff_softTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4) Tff7b72else Ta5d6ff"Ta5d6ffnativeTa5d6ff"
Te6edf3second Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Te6edf3contested Tff7b72= Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3secondTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72except Te6edf3StorageLockErrorTb4b4b4:
Te6edf3contested Tff7b72= Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected lock error (Tffd700{Te6edf3modeTffd700}Ta5d6ff): Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3secondTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffSecond lock acquire should have failed while held (Tffd700{Te6edf3modeTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3contestedTb4b4b4:
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffStorage lock did not reject a second holder (Tffd700{Te6edf3modeTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Te6edf3third Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Te6edf3thirdTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Te6edf3thirdTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
T8b949e# Soft-lock path used when flock is ENOSYS (Android / some FS). Exercise it
T8b949e# on every CI OS so regressions in the fallback are caught on Win/macOS/Linux.
Te6edf3soft_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ff.self_test_storage_lock_softTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3soft_dirTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3soft_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3soft_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3soft_result Tff7b72= Te6edf3_check_storage_lock_soft_fallbackTb4b4b4(Te6edf3soft_dirTb4b4b4)
Tff7b72if Te6edf3soft_resultTb4b4b4[Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4] Tff7b72!= Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3soft_result
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffStorage lock check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3lock_dirTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3lock_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3soft_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3base_dirTb4b4b4, Ta5d6ff"Ta5d6ff.self_test_storage_lock_softTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3soft_dirTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3soft_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ff_check_storage_lock_soft_fallbackTb4b4b4(Te6edf3lock_dirTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Force ENOSYS flock path and verify soft PID lock contest/release."""
Tff7b72import T7ee787errno
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3patch
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787storage_lock Tff7b72import Te6edf3StorageLockTb4b4b4, Te6edf3StorageLockError
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatform Tff7b72== Ta5d6ff"Ta5d6ffwin32Ta5d6ff"Tb4b4b4:
T8b949e# Windows uses msvcrt, so soft fallback is Unix-only. Still verify a second
T8b949e# native holder is rejected (covered above) and return ok here.
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ff_enosys_flockTb4b4b4(Tff7b72*Te6edf3_argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3_kwargsTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149OSErrorTb4b4b4(Te6edf3errnoTff7b72.Td2a8ffENOSYSTb4b4b4, Ta5d6ff"Ta5d6ffFunction not implementedTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6fffcntl.flockTa5d6ff"Tb4b4b4, Te6edf3side_effectTff7b72=Te6edf3_enosys_flockTb4b4b4)Tb4b4b4:
Te6edf3first Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Te6edf3firstTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Tffa657getattrTb4b4b4(Te6edf3firstTb4b4b4, Ta5d6ff"Ta5d6ff_softTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffExpected soft lock after flock ENOSYSTa5d6ff"Tb4b4b4)
Te6edf3second Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3secondTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72except Te6edf3StorageLockErrorTb4b4b4:
Tff7b72pass
Tff7b72elseTb4b4b4:
Te6edf3secondTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffSoft lock did not reject same-process second holderTa5d6ff"Tb4b4b4)
Te6edf3firstTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Te6edf3third Tff7b72= Te6edf3StorageLockTb4b4b4(Te6edf3lock_dirTb4b4b4)
Te6edf3thirdTff7b72.Td2a8ffacquireTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Tffa657getattrTb4b4b4(Te6edf3thirdTb4b4b4, Ta5d6ff"Ta5d6ff_softTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3thirdTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffSoft re-acquire after release did not use soft modeTa5d6ff"Tb4b4b4)
Te6edf3thirdTff7b72.Td2a8ffreleaseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffcheck_temp_filesystemTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Te6edf3path Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3fdTb4b4b4, Te6edf3path Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkstempTb4b4b4(Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchatx_self_check_Ta5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3fdTb4b4b4)
Te6edf3payload Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ffmeshchatx-temp-checkTa5d6ff"
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3handleTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Tff7b72if Te6edf3handleTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4) Tff7b72!= Te6edf3payloadTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffTemp file readback mismatchTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffTemp filesystem check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3path Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72def Td2a8ff_is_frozen_executableTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Tffa657getattrTb4b4b4(Te6edf3sysTb4b4b4, Ta5d6ff"Ta5d6fffrozenTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ff_frontend_source_availableTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""True when running from a source tree with Vite frontend sources.
Built meshchatx/public/ is gitignored and often absent in CI / E2E
(Vite serves the UI). Frozen desktop builds still require bundled public.
"""
Tff7b72tryTb4b4b4:
Te6edf3package_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Tff7b72__file__Tb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3frontend Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3package_dirTb4b4b4, Ta5d6ff"Ta5d6ffsrcTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffrontendTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3frontendTb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3frontendTb4b4b4, Ta5d6ff"Ta5d6ffmain.jsTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffcheck_public_assetsTb4b4b4(Te6edf3public_path_fnTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657strTb4b4b4]Tb4b4b4, Tffa657strTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3root Tff7b72= Te6edf3public_path_fnTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Te6edf3index_path Tff7b72= Te6edf3public_path_fnTb4b4b4(Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4) Tff7b72if Te6edf3root Tff7b72else Ta5d6ff"Ta5d6ff"
Tff7b72if Te6edf3root Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3rootTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3index_pathTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Te6edf3names Tff7b72= Tb4b4b4[Te6edf3n Tff7b72for Te6edf3n Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3rootTb4b4b4) Tff7b72if Tff7b72not Te6edf3nTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4)Tb4b4b4]
Tff7b72if Te6edf3namesTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
T8b949e# Source / CI / E2E: no built public dir, but frontend sources exist.
Tff7b72if Tff7b72not Te6edf3_is_frozen_executableTb4b4b4(Tb4b4b4) Tff7b72and Te6edf3_frontend_source_availableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72if Tff7b72not Te6edf3root Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3rootTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffPublic assets directory missing: Tffd700{Te6edf3rootTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffPublic assets directory is emptyTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffPublic assets check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheck_meshchatx_run_moduleTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Verify --meshchatx-run-module re-entry used by bots/rnsh on frozen builds."""
Te6edf3marker_dir Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchatx_run_module_check_Ta5d6ff"Tb4b4b4)
Te6edf3marker Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3marker_dirTb4b4b4, Ta5d6ff"Ta5d6ffprobe.outTa5d6ff"Tb4b4b4)
Te6edf3env Tff7b72= Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffcopyTb4b4b4(Tb4b4b4)
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHATX_SELF_CHECK_PROBE_PATHTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3marker
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffPYTHONUNBUFFEREDTa5d6ff"Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff1Ta5d6ff"
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_SKIP_STORAGE_LOCKTa5d6ff"Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff1Ta5d6ff"
T8b949e# Keep child logs/storage under the temp dir (Landlock RW + no user home writes).
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_LOG_DIRTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3marker_dirTb4b4b4, Ta5d6ff"Ta5d6fflogsTa5d6ff"Tb4b4b4)
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_STORAGE_DIRTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3marker_dirTb4b4b4, Ta5d6ff"Ta5d6ffstorageTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_LOG_DIRTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_STORAGE_DIRTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3cmd Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_SELF_CHECK_PROBE_MODULETb4b4b4,
Ta5d6ff"Ta5d6ffself-checkTa5d6ff"Tb4b4b4,
Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3cmd Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Ta5d6ff"Ta5d6ff-mTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffmeshchatx.meshchatTa5d6ff"Tb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_SELF_CHECK_PROBE_MODULETb4b4b4,
Ta5d6ff"Ta5d6ffself-checkTa5d6ff"Tb4b4b4,
Tb4b4b4]
Tff7b72tryTb4b4b4:
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(
Te6edf3cmdTb4b4b4,
Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3textTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff45Tb4b4b4,
Te6edf3checkTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3envTff7b72=Te6edf3envTb4b4b4,
Te6edf3stdinTff7b72=Te6edf3subprocessTff7b72.Td2a8ffDEVNULLTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0Tb4b4b4:
Te6edf3detail Tff7b72= Tb4b4b4(Te6edf3resultTff7b72.Td2a8ffstderr Tff7b72or Te6edf3resultTff7b72.Td2a8ffstdout Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4[Tff7b72-T79c0ff500Tb4b4b4:Tb4b4b4]
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffrun-module exited Tffd700{Te6edf3resultTff7b72.Td2a8ffreturncodeTffd700}Ta5d6ff: Tffd700{Te6edf3detail Tff7b72or Ta5d6ff'Ta5d6ffno outputTa5d6ff'Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3markerTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffProbe marker file was not writtenTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3markerTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3text Tff7b72= Te6edf3handleTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ffokTa5d6ff" Tff7b72not Tff7b72in Te6edf3text Tff7b72or Ta5d6ff"Ta5d6ffself-checkTa5d6ff" Tff7b72not Tff7b72in Te6edf3textTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected probe output: Tffd700{Te6edf3textTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Te6edf3subprocessTff7b72.Td2a8ffTimeoutExpiredTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffrun-module probe timed outTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffrun-module check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3marker_dirTb4b4b4, Te6edf3ignore_errorsTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72def Td2a8ffcheck_subprocess_spawnTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Spawn a short-lived child process (covers Windows CreateProcess / POSIX fork).
Frozen desktop builds (AppImage / EXE / macOS) set sys.executable to
MeshChatX itself, which rejects Python -c. Those builds re-enter via
--meshchatx-run-module like bots and rnsh.
"""
Tff7b72tryTb4b4b4:
Te6edf3env Tff7b72= Tb4b4b4{Tff7b72*Tff7b72*Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4, Ta5d6ff"Ta5d6ffPYTHONUNBUFFEREDTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4}
Tff7b72if Te6edf3_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3envTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_SKIP_STORAGE_LOCKTa5d6ff"Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff1Ta5d6ff"
Te6edf3cmd Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_SELF_CHECK_PROBE_MODULETb4b4b4,
Ta5d6ff"Ta5d6ffspawn-okTa5d6ff"Tb4b4b4,
Tb4b4b4]
Te6edf3expected Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx-self-check-probeTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3cmd Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Ta5d6ff"Ta5d6ff-cTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffprint(Ta5d6ff'Ta5d6ffmeshchatx-spawn-okTa5d6ff'Ta5d6ff, flush=True)Ta5d6ff"Tb4b4b4,
Tb4b4b4]
Te6edf3expected Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx-spawn-okTa5d6ff"
Te6edf3result Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(
Te6edf3cmdTb4b4b4,
Te6edf3capture_outputTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3textTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff30Tb4b4b4,
Te6edf3checkTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3envTff7b72=Te6edf3envTb4b4b4,
Te6edf3stdinTff7b72=Te6edf3subprocessTff7b72.Td2a8ffDEVNULLTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3resultTff7b72.Td2a8ffreturncode Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffspawn exited Tffd700{Te6edf3resultTff7b72.Td2a8ffreturncodeTffd700}Ta5d6ff: Tffd700{Tb4b4b4(Te6edf3resultTff7b72.Td2a8ffstderr Tff7b72or Te6edf3resultTff7b72.Td2a8ffstdout Tff7b72or Ta5d6ff'Ta5d6ff'Tb4b4b4)Tb4b4b4[Tff7b72-T79c0ff300Tb4b4b4:Tb4b4b4]Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3expected Tff7b72not Tff7b72in Tb4b4b4(Te6edf3resultTff7b72.Td2a8ffstdout Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected spawn output: Tffd700{Te6edf3resultTff7b72.Td2a8ffstdoutTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffSubprocess spawn check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheck_sqlite_roundtripTb4b4b4(Te6edf3base_dirTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Create a temp SQLite DB, write a row, read it back, then delete the file."""
Tff7b72import T7ee787sqlite3
Te6edf3root Tff7b72= Te6edf3base_dir Tff7b72if Te6edf3base_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3base_dirTb4b4b4) Tff7b72else Te6edf3tempfileTff7b72.Td2a8ffgettempdirTb4b4b4(Tb4b4b4)
Te6edf3path Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3fdTb4b4b4, Te6edf3path Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkstempTb4b4b4(
Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchatx_self_check_Ta5d6ff"Tb4b4b4,
Te6edf3suffixTff7b72=Ta5d6ff"Ta5d6ff.dbTa5d6ff"Tb4b4b4,
Tffa657dirTff7b72=Te6edf3rootTb4b4b4,
Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3fdTb4b4b4)
Te6edf3conn Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffconnectTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3connTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffCREATE TABLE probe (id INTEGER PRIMARY KEY, note TEXT)Ta5d6ff"Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffINSERT INTO probe (note) VALUES (?)Ta5d6ff"Tb4b4b4,
Tb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx-sqlite-okTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Te6edf3row Tff7b72= Te6edf3connTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffSELECT note FROM probe WHERE id = 1Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8fffetchoneTb4b4b4(Tb4b4b4)
Tff7b72finallyTb4b4b4:
Te6edf3connTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3row Tff7b72or Te6edf3rowTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72!= Ta5d6ff"Ta5d6ffmeshchatx-sqlite-okTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected SQLite readback: Tffd700{Te6edf3rowTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffSQLite roundtrip failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3path Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72def Td2a8ffcheck_identity_file_roundtripTb4b4b4(Te6edf3base_dirTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Generate a Reticulum identity, save to disk, reload, and compare hashes."""
Tff7b72tryTb4b4b4:
Tff7b72import T7ee787RNS
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffRNS import failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3root Tff7b72= Te6edf3base_dir Tff7b72if Te6edf3base_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3base_dirTb4b4b4) Tff7b72else Te6edf3tempfileTff7b72.Td2a8ffgettempdirTb4b4b4(Tb4b4b4)
Te6edf3path Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3fdTb4b4b4, Te6edf3path Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkstempTb4b4b4(
Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ffmeshchatx_id_Ta5d6ff"Tb4b4b4,
Te6edf3suffixTff7b72=Ta5d6ff"Ta5d6ff.identityTa5d6ff"Tb4b4b4,
Tffa657dirTff7b72=Te6edf3rootTb4b4b4,
Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffcloseTb4b4b4(Te6edf3fdTb4b4b4)
Te6edf3identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Te6edf3create_keysTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3orig_hash Tff7b72= Te6edf3identityTff7b72.Td2a8ffhash
Tff7b72if Te6edf3orig_hash Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffGenerated identity hash is NoneTa5d6ff"Tb4b4b4)
Te6edf3original Tff7b72= Tffa657bytesTb4b4b4(Te6edf3orig_hashTb4b4b4)
Te6edf3priv_key Tff7b72= Te6edf3identityTff7b72.Td2a8ffget_private_keyTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3priv_key Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffGenerated private key is NoneTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3handleTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3priv_keyTb4b4b4)
Te6edf3loaded Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Te6edf3create_keysTff7b72=Tff7b72FalseTb4b4b4)
Te6edf3loadedTff7b72.Td2a8ffloadTb4b4b4(Te6edf3pathTb4b4b4)
Te6edf3loaded_hash Tff7b72= Te6edf3loadedTff7b72.Td2a8ffhash
Tff7b72if Te6edf3loaded_hash Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffLoaded identity hash is NoneTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657bytesTb4b4b4(Te6edf3loaded_hashTb4b4b4) Tff7b72!= Te6edf3originalTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffReloaded identity hash mismatchTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffIdentity file roundtrip failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72if Te6edf3path Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72def Td2a8ffcheck_loopback_tcpTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Bind and accept a short-lived TCP connection on 127.0.0.1."""
Tff7b72import T7ee787socket
Tff7b72import T7ee787threading
Tff7b72tryTb4b4b4:
Te6edf3server Tff7b72= Te6edf3socketTff7b72.Td2a8ffsocketTb4b4b4(Te6edf3socketTff7b72.Td2a8ffAF_INETTb4b4b4, Te6edf3socketTff7b72.Td2a8ffSOCK_STREAMTb4b4b4)
Te6edf3serverTff7b72.Td2a8ffsetsockoptTb4b4b4(Te6edf3socketTff7b72.Td2a8ffSOL_SOCKETTb4b4b4, Te6edf3socketTff7b72.Td2a8ffSO_REUSEADDRTb4b4b4, T79c0ff1Tb4b4b4)
Te6edf3serverTff7b72.Td2a8ffbindTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ff127.0.0.1Ta5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4)
Te6edf3serverTff7b72.Td2a8fflistenTb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3hostTb4b4b4, Te6edf3port Tff7b72= Te6edf3serverTff7b72.Td2a8ffgetsocknameTb4b4b4(Tb4b4b4)
Te6edf3receivedTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657bytesTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72def Td2a8ff_acceptTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3connTb4b4b4, Te6edf3_addr Tff7b72= Te6edf3serverTff7b72.Td2a8ffacceptTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3receivedTb4b4b4[Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3connTff7b72.Td2a8ffrecvTb4b4b4(T79c0ff64Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffsendallTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffmeshchatx-tcp-okTa5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Te6edf3connTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Te6edf3thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Te6edf3_acceptTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Te6edf3client Tff7b72= Te6edf3socketTff7b72.Td2a8ffcreate_connectionTb4b4b4(Tb4b4b4(Te6edf3hostTb4b4b4, Te6edf3portTb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3clientTff7b72.Td2a8ffsendallTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffpingTa5d6ff"Tb4b4b4)
Te6edf3reply Tff7b72= Te6edf3clientTff7b72.Td2a8ffrecvTb4b4b4(T79c0ff64Tb4b4b4)
Tff7b72finallyTb4b4b4:
Te6edf3clientTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Te6edf3threadTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4)
Te6edf3serverTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3receivedTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4) Tff7b72!= Ta5d6ffbTa5d6ff"Ta5d6ffpingTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffServer received Tffd700{Te6edf3receivedTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6ffdataTa5d6ff'Tb4b4b4)Tffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3reply Tff7b72!= Ta5d6ffbTa5d6ff"Ta5d6ffmeshchatx-tcp-okTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected client reply: Tffd700{Te6edf3replyTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffLoopback TCP check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheck_unicode_pathTb4b4b4(Te6edf3base_dirTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Write and read a file whose name contains non-ASCII characters."""
Te6edf3root Tff7b72= Te6edf3base_dir Tff7b72if Te6edf3base_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3base_dirTb4b4b4) Tff7b72else Te6edf3tempfileTff7b72.Td2a8ffgettempdirTb4b4b4(Tb4b4b4)
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_self_check_ユニコード.txtTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3payload Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx-unicode-ok-αβγTa5d6ff"
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3handleTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Tff7b72if Te6edf3handleTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4) Tff7b72!= Te6edf3payloadTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffUnicode path readback mismatchTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnicode path check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72def Td2a8ffcheck_rnode_supportTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Import rnode_support and verify transport classification helpers."""
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3rnode_support Tff7b72as Te6edf3rn
Te6edf3cases Tff7b72= Tb4b4b4(
Tb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffportTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftcp://127.0.0.1Ta5d6ff"Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6fftcpTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffportTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffble://aa:bb:cc:dd:ee:ffTa5d6ff"Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffbleTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffportTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff/dev/ttyUSB0Ta5d6ff"Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffserialTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffportTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffallow_bluetoothTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftrueTa5d6ff"Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffbluetooth_classicTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3ifaceTb4b4b4, Te6edf3expected Tff7b72in Te6edf3casesTb4b4b4:
Te6edf3got Tff7b72= Te6edf3rnTff7b72.Td2a8ff_rnode_iface_transportTb4b4b4(Te6edf3ifaceTb4b4b4)
Tff7b72if Te6edf3got Tff7b72!= Te6edf3expectedTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6fftransport for Tffd700{Te6edf3ifaceTffd700!r}Ta5d6ff was Tffd700{Te6edf3gotTffd700!r}Ta5d6ff, expected Tffd700{Te6edf3expectedTffd700!r}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3rnTff7b72.Td2a8ffrnode_port_is_tcpTb4b4b4(Ta5d6ff"Ta5d6fftcp://127.0.0.1Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffrnode_port_is_tcp rejected tcp://127.0.0.1Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3rnTff7b72.Td2a8ffrnode_port_is_tcpTb4b4b4(Ta5d6ff"Ta5d6ff/dev/ttyUSB0Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffrnode_port_is_tcp accepted serial pathTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffRNode support check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheck_bot_launcherTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Verify BotHandler launcher argv for frozen and unfrozen modes."""
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3patch
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787bot_handler Tff7b72import Tb4b4b4(
Te6edf3_BOT_PROCESS_MODULETb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3BotHandlerTb4b4b4,
Tb4b4b4)
Te6edf3handler Tff7b72= Te6edf3BotHandlerTff7b72.Td2a8ff__new__Tb4b4b4(Te6edf3BotHandlerTb4b4b4)
Te6edf3handlerTff7b72.Td2a8ffrunner_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Ta5d6ff"Ta5d6fffakeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbot_process.pyTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3patchTff7b72.Td2a8ffobjectTb4b4b4(Te6edf3BotHandlerTb4b4b4, Ta5d6ff"Ta5d6ff_is_frozen_executableTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Te6edf3unfrozen Tff7b72= Te6edf3handlerTff7b72.Td2a8ff_resolve_bot_launcherTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3unfrozen Tff7b72!= Tb4b4b4[Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4, Te6edf3handlerTff7b72.Td2a8ffrunner_pathTb4b4b4]Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected unfrozen launcher: Tffd700{Te6edf3unfrozenTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72with Te6edf3patchTff7b72.Td2a8ffobjectTb4b4b4(Te6edf3BotHandlerTb4b4b4, Ta5d6ff"Ta5d6ff_is_frozen_executableTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
Te6edf3frozen Tff7b72= Te6edf3handlerTff7b72.Td2a8ff_resolve_bot_launcherTb4b4b4(Tb4b4b4)
Te6edf3expected_frozen Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_BOT_PROCESS_MODULETb4b4b4,
Tb4b4b4]
Tff7b72if Te6edf3frozen Tff7b72!= Te6edf3expected_frozenTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffUnexpected frozen launcher: Tffd700{Te6edf3frozenTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffBot launcher check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ff_ensure_app_session_secretTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657getattrTb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffsession_secret_keyTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72return
Te6edf3secret Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3appTff7b72.Td2a8ffconfig Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3secret Tff7b72= Te6edf3appTff7b72.Td2a8ffconfigTff7b72.Td2a8ffauth_session_secretTff7b72.Td2a8ffgetTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3secret Tff7b72= Tff7b72None
Tff7b72if Tff7b72not Te6edf3secretTb4b4b4:
Tff7b72import T7ee787secrets
Te6edf3secret Tff7b72= Te6edf3secretsTff7b72.Td2a8fftoken_urlsafeTb4b4b4(T79c0ff32Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3appTff7b72.Td2a8ffconfig Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3appTff7b72.Td2a8ffconfigTff7b72.Td2a8ffauth_session_secretTff7b72.Td2a8ffsetTb4b4b4(Te6edf3secretTb4b4b4)
Te6edf3appTff7b72.Td2a8ffsession_secret_key Tff7b72= Te6edf3secret
Tff7b72def Td2a8ff_ensure_awaitable_methodTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4, Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Ensure app.name is awaitable (unit tests often patch with sync MagicMock)."""
Tff7b72import T7ee787asyncio
Te6edf3method Tff7b72= Tffa657getattrTb4b4b4(Te6edf3appTb4b4b4, Te6edf3nameTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3method Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3result Tff7b72= Te6edf3methodTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149TypeErrorTb4b4b4:
Tff7b72return
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return
Tff7b72if Te6edf3asyncioTff7b72.Td2a8ffiscoroutineTb4b4b4(Te6edf3resultTb4b4b4)Tb4b4b4:
Te6edf3resultTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72return
Tff7b72async Tff7b72def Td2a8ff_noopTb4b4b4(Tff7b72*Te6edf3_argsTb4b4b4, Tff7b72*Tff7b72*Te6edf3_kwargsTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tffa657objectTff7b72.Td2a8ff__setattr__Tb4b4b4(Te6edf3appTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3_noopTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tffa657setattrTb4b4b4(Te6edf3appTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3_noopTb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_build_probe_aio_appTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4)Tb4b4b4:
Tff7b72import T7ee787asyncio
Tff7b72from T7ee787aiohttp Tff7b72import Te6edf3web
Tff7b72from T7ee787aiohttp_session Tff7b72import Te6edf3setup Tff7b72as Te6edf3setup_session
Te6edf3_ensure_app_session_secretTb4b4b4(Te6edf3appTb4b4b4)
Te6edf3_ensure_awaitable_methodTb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffsend_config_to_websocket_clientsTa5d6ff"Tb4b4b4)
Te6edf3broadcast Tff7b72= Tffa657getattrTb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffwebsocket_broadcastTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Tffa657callableTb4b4b4(Te6edf3broadcastTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3maybe Tff7b72= Te6edf3broadcastTb4b4b4(Ta5d6ff"Tffd700{}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3asyncioTff7b72.Td2a8ffiscoroutineTb4b4b4(Te6edf3maybeTb4b4b4)Tb4b4b4:
Te6edf3maybeTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72async Tff7b72def Td2a8ff_broadcastTb4b4b4(Te6edf3_dataTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tffa657objectTff7b72.Td2a8ff__setattr__Tb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffwebsocket_broadcastTa5d6ff"Tb4b4b4, Te6edf3_broadcastTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3appTff7b72.Td2a8ffwebsocket_broadcast Tff7b72= Te6edf3_broadcast
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Te6edf3routes Tff7b72= Te6edf3webTff7b72.Td2a8ffRouteTableDefTb4b4b4(Tb4b4b4)
Te6edf3auth_mwTb4b4b4, Te6edf3mime_mwTb4b4b4, Te6edf3sec_mwTb4b4b4, Te6edf3csrf_mwTb4b4b4, Te6edf3ip_mw Tff7b72= Te6edf3appTff7b72.Td2a8ff_define_routesTb4b4b4(Te6edf3routesTb4b4b4)
Te6edf3aio_app Tff7b72= Te6edf3webTff7b72.Td2a8ffApplicationTb4b4b4(
Te6edf3middlewaresTff7b72=Tb4b4b4[Te6edf3auth_mwTb4b4b4, Te6edf3mime_mwTb4b4b4, Te6edf3sec_mwTb4b4b4, Te6edf3csrf_mwTb4b4b4, Te6edf3ip_mwTb4b4b4]Tb4b4b4,
Tb4b4b4)
Te6edf3setup_sessionTb4b4b4(Te6edf3aio_appTb4b4b4, Te6edf3appTff7b72.Td2a8ff_encrypted_cookie_storageTb4b4b4(Te6edf3use_httpsTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4)
Te6edf3aio_appTff7b72.Td2a8ffadd_routesTb4b4b4(Te6edf3routesTb4b4b4)
Tff7b72return Te6edf3aio_app
Te6edf3_WEB_PROBE_KEYS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffhttp_status_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_app_info_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_config_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_db_health_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_bots_status_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_security_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_interfaces_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_reticulum_instance_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_identities_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_favourites_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_telephone_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_plugins_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_plugins_trust_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_sideband_plugins_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_sideband_config_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_rrc_hubs_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffhttp_rrc_servers_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffwebsocket_rns_link_goodTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8ffcheck_plugins_runtimeTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Verify plugin manager is wired and bundled example is available when enabled."""
Te6edf3manager Tff7b72= Tffa657getattrTb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffplugin_managerTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3manager Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffplugin_manager is not initializedTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3plugins Tff7b72= Te6edf3managerTff7b72.Td2a8fflist_pluginsTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6fflist_plugins failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3pluginsTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fflist_plugins did not return a listTa5d6ff"Tb4b4b4)
Te6edf3plugins_enabled Tff7b72= Tffa657boolTb4b4b4(Tffa657getattrTb4b4b4(Te6edf3appTb4b4b4, Ta5d6ff"Ta5d6ffplugins_enabledTa5d6ff"Tb4b4b4, Tff7b72TrueTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3plugins_enabledTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Te6edf3bundled_id Tff7b72= Ta5d6ff"Ta5d6ffcom.meshchatx.mcx-bugsTa5d6ff"
Tff7b72if Tffa657anyTb4b4b4(Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bundled_id Tff7b72for Te6edf3item Tff7b72in Te6edf3pluginsTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3managerTff7b72.Td2a8ffinstall_bundled_examplesTb4b4b4(Tb4b4b4)
Te6edf3plugins Tff7b72= Te6edf3managerTff7b72.Td2a8fflist_pluginsTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffinstall_bundled_examples failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tffa657anyTb4b4b4(Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bundled_id Tff7b72for Te6edf3item Tff7b72in Te6edf3pluginsTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffbundled plugin Tffd700{Te6edf3bundled_idTffd700}Ta5d6ff missing after installTa5d6ff"Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_probe_rns_link_apiTb4b4b4(Te6edf3wsTb4b4b4: Te6edf3AnyTb4b4b4, Tff7b72*Tb4b4b4, Te6edf3timeoutTb4b4b4: Tffa657float Tff7b72= T79c0ff10.0Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
T8b949e"""Exercise generic rns.link.* handlers without requiring a live mesh peer."""
Tff7b72import T7ee787asyncio
Tff7b72import T7ee787json
Tff7b72from T7ee787aiohttp Tff7b72import Te6edf3WSMsgType
Te6edf3request_id Tff7b72= Ta5d6ff"Ta5d6ffself-check-rns-linkTa5d6ff"
Tff7b72tryTb4b4b4:
Tff7b72await Te6edf3wsTff7b72.Td2a8ffsend_strTb4b4b4(
Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffrns.link.closeTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4,
Ta5d6ff"Ta5d6ffaspectTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmeshchatx.selfcheckTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrequest_idTa5d6ff"Tb4b4b4: Te6edf3request_idTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3deadline Tff7b72= Te6edf3asyncioTff7b72.Td2a8ffget_event_loopTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3timeout
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3remaining Tff7b72= Te6edf3deadline Tff7b72- Te6edf3asyncioTff7b72.Td2a8ffget_event_loopTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3remaining Tff7b72<Tff7b72= T79c0ff0Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffrns.link.close reply timed outTa5d6ff"Tb4b4b4)
Te6edf3msg Tff7b72= Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(Te6edf3wsTff7b72.Td2a8ffreceiveTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3remainingTb4b4b4)
Tff7b72if Te6edf3msgTff7b72.Td2a8fftype Tff7b72!= Te6edf3WSMsgTypeTff7b72.Td2a8ffTEXTTb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3msgTff7b72.Td2a8ffdataTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72continue
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3payloadTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4) Tff7b72!= Ta5d6ff"Ta5d6ffrns.link.closeTa5d6ff"Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffrequest_idTa5d6ff"Tb4b4b4) Tff7b72!= Te6edf3request_idTb4b4b4:
Tff7b72continue
Te6edf3status Tff7b72= Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3status Tff7b72not Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffailureTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffunexpected status=Tffd700{Te6edf3statusTffd700!r}Ta5d6ff"Tb4b4b4)
T8b949e# No cached link is expected in self-check, so failure is the normal path.
Tff7b72if Te6edf3status Tff7b72== Ta5d6ff"Ta5d6fffailureTa5d6ff" Tff7b72and Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffailure_reasonTa5d6ff"Tb4b4b4) Tff7b72not Tff7b72in Tb4b4b4(
Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffno_active_linkTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffunexpected failure_reason=Tffd700{Te6edf3payloadTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6fffailure_reasonTa5d6ff'Tb4b4b4)Tffd700!r}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149TimeoutErrorTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffrns.link.close reply timed outTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4: Te6edf3AnyTb4b4b4,
Te6edf3pathTb4b4b4: Tffa657strTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3require_keysTb4b4b4: Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tff7b72.Tff7b72.Tff7b72.Tb4b4b4] Tff7b72= Tb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3require_nestedTb4b4b4: Tffa657tupleTb4b4b4[Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657typeTb4b4b4]Tb4b4b4, Tff7b72.Tff7b72.Tff7b72.Tb4b4b4] Tff7b72= Tb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3validateTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4]Tb4b4b4, Tffa657str Tff7b72| Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3timeoutTb4b4b4: Tffa657float Tff7b72= T79c0ff15.0Tb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Tff7b72import T7ee787asyncio
Tff7b72async Tff7b72def Td2a8ff_onceTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4:
Te6edf3resp Tff7b72= Tff7b72await Te6edf3clientTff7b72.Td2a8ffgetTb4b4b4(Te6edf3pathTb4b4b4)
Te6edf3body Tff7b72= Tff7b72await Te6edf3respTff7b72.Td2a8ffjsonTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3respTff7b72.Td2a8ffstatus Tff7b72!= T79c0ff200 Tff7b72or Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3bodyTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff status=Tffd700{Te6edf3respTff7b72.Td2a8ffstatusTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3key Tff7b72in Te6edf3require_keysTb4b4b4:
Tff7b72if Te6edf3key Tff7b72not Tff7b72in Te6edf3bodyTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff missing key Tffd700{Te6edf3keyTffd700!r}Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3keyTb4b4b4, Te6edf3expected_type Tff7b72in Te6edf3require_nestedTb4b4b4:
Te6edf3value Tff7b72= Te6edf3bodyTff7b72.Td2a8ffgetTb4b4b4(Te6edf3keyTb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Te6edf3expected_typeTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff key Tffd700{Te6edf3keyTffd700!r}Ta5d6ff type=Tffd700{Tffa657typeTb4b4b4(Te6edf3valueTb4b4b4)Tff7b72.Td2a8ff__name__Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3validate Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3reason Tff7b72= Te6edf3validateTb4b4b4(Te6edf3bodyTb4b4b4)
Tff7b72if Te6edf3reasonTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Te6edf3reasonTb4b4b4)
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72return Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(Te6edf3_onceTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72except Tf85149TimeoutErrorTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff timed out after Tffd700{Te6edf3timeoutTffd700:Ta5d6ff.0fTffd700}Ta5d6ffsTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Tffd700{Te6edf3pathTffd700}Ta5d6ff: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ff_run_web_api_probesTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4]Tb4b4b4:
T8b949e"""Hit critical HTTP + WebSocket endpoints on an ephemeral TestServer."""
Tff7b72import T7ee787asyncio
Tff7b72import T7ee787json
Tff7b72from T7ee787aiohttp Tff7b72import Te6edf3WSMsgType
Tff7b72from T7ee787aiohttpT7ee787.T7ee787test_utils Tff7b72import Te6edf3TestClientTb4b4b4, Te6edf3TestServer
Te6edf3resultsTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4] Tff7b72= Tb4b4b4{
Te6edf3keyTb4b4b4: Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffnot runTa5d6ff"Tb4b4b4) Tff7b72for Te6edf3key Tff7b72in Te6edf3_WEB_PROBE_KEYS
Tb4b4b4}
Tff7b72tryTb4b4b4:
Te6edf3aio_app Tff7b72= Tff7b72await Te6edf3_build_probe_aio_appTb4b4b4(Te6edf3appTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3failed Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffFailed to build probe app: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tffa657dictTff7b72.Td2a8fffromkeysTb4b4b4(Te6edf3resultsTb4b4b4, Te6edf3failedTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72async Tff7b72with Te6edf3TestClientTb4b4b4(Te6edf3TestServerTb4b4b4(Te6edf3aio_appTb4b4b4)Tb4b4b4) Tff7b72as Te6edf3clientTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_status_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/statusTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3validateTff7b72=Tff7b72lambda Te6edf3bodyTb4b4b4: Tb4b4b4(
Tff7b72None Tff7b72if Te6edf3bodyTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffokTa5d6ff" Tff7b72else Ta5d6fffTa5d6ff"Ta5d6ffstatus body=Tffd700{Te6edf3bodyTffd700!r}Ta5d6ff"
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_app_info_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/app/infoTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffapp_infoTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3validateTff7b72=Tff7b72lambda Te6edf3bodyTb4b4b4: Tb4b4b4(
Tff7b72None
Tff7b72if Te6edf3bodyTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffapp_infoTa5d6ff"Tb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4)
Tff7b72else Ta5d6ff"Ta5d6ffapp_info.version missingTa5d6ff"
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_config_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/configTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_db_health_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/database/healthTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffdatabaseTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3resp Tff7b72= Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ff/api/v1/auth/csrfTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff15Tb4b4b4,
Tb4b4b4)
Te6edf3body Tff7b72= Tff7b72await Te6edf3respTff7b72.Td2a8ffjsonTb4b4b4(Tb4b4b4)
Te6edf3token Tff7b72= Te6edf3bodyTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffcsrf_tokenTa5d6ff"Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3bodyTb4b4b4, Tffa657dictTb4b4b4) Tff7b72else Tff7b72None
Tff7b72if Te6edf3respTff7b72.Td2a8ffstatus Tff7b72!= T79c0ff200 Tff7b72or Tff7b72not Te6edf3tokenTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffcsrf status=Tffd700{Te6edf3respTff7b72.Td2a8ffstatusTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3auth_resp Tff7b72= Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(
Te6edf3clientTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ff/api/v1/auth/statusTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff15Tb4b4b4,
Tb4b4b4)
Te6edf3auth_body Tff7b72= Tff7b72await Te6edf3auth_respTff7b72.Td2a8ffjsonTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3auth_respTff7b72.Td2a8ffstatus Tff7b72!= T79c0ff200 Tff7b72or Ta5d6ff"Ta5d6ffauth_enabledTa5d6ff" Tff7b72not Tff7b72in Te6edf3auth_bodyTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffauth/status status=Tffd700{Te6edf3auth_respTff7b72.Td2a8ffstatusTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72except Tf85149TimeoutErrorTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffauth csrf timed outTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_auth_csrf_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_bots_status_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/bots/statusTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftemplatesTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_security_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/server/securityTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6fflisten_hostTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflisten_portTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffauth_enabledTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_interfaces_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/reticulum/interfacesTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffinterfacesTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_reticulum_instance_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/reticulum/instanceTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3validateTff7b72=Tff7b72lambda Te6edf3bodyTb4b4b4: Tb4b4b4(
Tff7b72None
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3bodyTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657dictTb4b4b4)
Tff7b72and Ta5d6ff"Ta5d6ffshare_instanceTa5d6ff" Tff7b72in Te6edf3bodyTb4b4b4[Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4]
Tff7b72and Ta5d6ff"Ta5d6fflocal_hops_deltaTa5d6ff" Tff7b72in Te6edf3bodyTb4b4b4[Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4]
Tff7b72else Ta5d6ff"Ta5d6ffinstance missing share_instance/local_hops_deltaTa5d6ff"
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_identities_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/identitiesTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffidentitiesTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_favourites_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/favouritesTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6fffavouritesTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_telephone_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/telephone/statusTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_plugins_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/pluginsTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ffplugins_enabledTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffpluginsTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_plugins_trust_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/plugins/trusted-publishersTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6fftamperedTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffpublishersTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_sideband_plugins_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/sideband-pluginsTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4, Tb4b4b4(Ta5d6ff"Ta5d6ffpluginsTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_sideband_config_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/sideband-plugins/configTa5d6ff"Tb4b4b4,
Te6edf3require_keysTff7b72=Tb4b4b4(
Ta5d6ff"Ta5d6ffservice_plugins_enabledTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffcommand_plugins_enabledTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_rrc_hubs_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/hubsTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffhubsTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffhttp_rrc_servers_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_json_getTb4b4b4(
Te6edf3clientTb4b4b4,
Ta5d6ff"Ta5d6ff/api/v1/rrc/serversTa5d6ff"Tb4b4b4,
Te6edf3require_nestedTff7b72=Tb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ffhubsTa5d6ff"Tb4b4b4, Tffa657listTb4b4b4)Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3ws Tff7b72= Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(Te6edf3clientTff7b72.Td2a8ffws_connectTb4b4b4(Ta5d6ff"Ta5d6ff/wsTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=T79c0ff15Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3msg Tff7b72= Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffwait_forTb4b4b4(Te6edf3wsTff7b72.Td2a8ffreceiveTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4)
Tff7b72except Tf85149TimeoutErrorTb4b4b4:
Tff7b72if Te6edf3wsTff7b72.Td2a8ffclosedTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6ff"Ta5d6ffws closed without first messageTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
T8b949e# Connection works, and first push may be absent under test doubles.
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72if Te6edf3msgTff7b72.Td2a8fftype Tff7b72not Tff7b72in Tb4b4b4(Te6edf3WSMsgTypeTff7b72.Td2a8ffTEXTTb4b4b4, Te6edf3WSMsgTypeTff7b72.Td2a8ffBINARYTb4b4b4)Tb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6fffTa5d6ff"Ta5d6ffunexpected ws message type=Tffd700{Te6edf3msgTff7b72.Td2a8fftypeTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elif Te6edf3msgTff7b72.Td2a8fftype Tff7b72== Te6edf3WSMsgTypeTff7b72.Td2a8ffTEXTTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3payload Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3msgTff7b72.Td2a8ffdataTb4b4b4)
Te6edf3ok Tff7b72= Tffa657isinstanceTb4b4b4(Te6edf3payloadTb4b4b4, Tffa657dictTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3ok Tff7b72= Tff7b72False
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Te6edf3okTb4b4b4,
Ta5d6ff"Ta5d6ff" Tff7b72if Te6edf3ok Tff7b72else Ta5d6ff"Ta5d6fffirst ws message was not JSON objectTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72if Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_rns_link_goodTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72await Te6edf3_probe_rns_link_apiTb4b4b4(
Te6edf3wsTb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_rns_link_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(
Tff7b72FalseTb4b4b4,
Ta5d6ff"Ta5d6ffskipped: websocket_good failedTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72await Te6edf3wsTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4)
Te6edf3resultsTb4b4b4[Ta5d6ff"Ta5d6ffwebsocket_rns_link_goodTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3failed Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffWeb probe client failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3key Tff7b72in Te6edf3resultsTb4b4b4:
Tff7b72if Te6edf3resultsTb4b4b4[Te6edf3keyTb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4] Tff7b72!= Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4:
Te6edf3resultsTb4b4b4[Te6edf3keyTb4b4b4] Tff7b72= Te6edf3failed
Tff7b72return Te6edf3results
Tff7b72def Td2a8ffcheck_web_stackTb4b4b4(Te6edf3appTb4b4b4: Te6edf3AnyTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4]Tb4b4b4:
T8b949e"""Run HTTP/WebSocket probes against an ephemeral aiohttp TestServer."""
Tff7b72import T7ee787asyncio
Tff7b72tryTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3asyncioTff7b72.Td2a8ffget_running_loopTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149RuntimeErrorTb4b4b4:
Tff7b72return Te6edf3asyncioTff7b72.Td2a8ffrunTb4b4b4(Te6edf3_run_web_api_probesTb4b4b4(Te6edf3appTb4b4b4)Tb4b4b4)
T8b949e# Already inside an event loop (e.g. aiohttp request handler).
Tff7b72import T7ee787concurrentT7ee787.T7ee787futures
Tff7b72with Te6edf3concurrentTff7b72.Td2a8fffuturesTff7b72.Td2a8ffThreadPoolExecutorTb4b4b4(Te6edf3max_workersTff7b72=T79c0ff1Tb4b4b4) Tff7b72as Te6edf3poolTb4b4b4:
Tff7b72return Te6edf3poolTff7b72.Td2a8ffsubmitTb4b4b4(Tff7b72lambdaTb4b4b4: Te6edf3asyncioTff7b72.Td2a8ffrunTb4b4b4(Te6edf3_run_web_api_probesTb4b4b4(Te6edf3appTb4b4b4)Tb4b4b4)Tb4b4b4)Tff7b72.Td2a8ffresultTb4b4b4(
Te6edf3timeoutTff7b72=T79c0ff90Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3failed Tff7b72= Te6edf3_statusTb4b4b4(Tff7b72FalseTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffWeb stack check failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tffa657dictTff7b72.Td2a8fffromkeysTb4b4b4(Te6edf3_WEB_PROBE_KEYSTb4b4b4, Te6edf3failedTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────